﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Metadata.W3cXsd2001;

namespace Logic.Packet
{
    public class T4CBasePak : IT4CPak
    {
        //public int Id
        //{
        //    get
        //    {
        //        ushort headerShort = ushort.Parse(new SoapHexBinary(Data.Take(2).Reverse().ToArray()).ToString(), System.Globalization.NumberStyles.HexNumber);
        //        string binaryString = Convert.ToString(headerShort, 2);

        //        if (binaryString.Length > 15)
        //        {
        //            SecondCrypto = Convert.ToBoolean(Convert.ToInt32(binaryString[13].ToString()));
        //            FragmentTail = Convert.ToBoolean(Convert.ToInt32(binaryString[14].ToString()));
        //            NeedAck = Convert.ToBoolean(Convert.ToInt32(binaryString[15].ToString()));

        //            return Convert.ToInt32(binaryString.Substring(0, 13), 2);
        //        }
        //        return -1;
        //    }
        //    set;
        //}

        public string Signature
        {
            //get
            //{
            //    if (Data.Length > 2)
            //        return new SoapHexBinary((byte[])Data.Skip(2).Take(4).ToArray()).ToString();
            //    return "ACK REPLY";

            //}
            //set;
            get;
            set;
        }
        public string ActionID
        {
            //get
            //{
            //    if (Data.Length > 2)
            //    {
            //        if (this.Type == PacketType.Client && Paks.ClientPaks.ContainsKey(new SoapHexBinary((byte[])Data.Skip(6).Take(2).ToArray()).ToString()))
            //            return Paks.ClientPaks[new SoapHexBinary((byte[])Data.Skip(6).Take(2).ToArray()).ToString()];
            //        else if (this.Type == PacketType.Server && Paks.ServerPaks.ContainsKey(new SoapHexBinary((byte[])Data.Skip(6).Take(2).ToArray()).ToString()))
            //            return Paks.ServerPaks[new SoapHexBinary((byte[])Data.Skip(6).Take(2).ToArray()).ToString()];
            //        else
            //            return new SoapHexBinary((byte[])Data.Skip(6).Take(2).ToArray()).ToString();
            //    }
            //    return "ACK REPLY";
            //}
            //set {};
            get;
            set;
        }
        public string Checksum
        {
            //get
            //{
            //    if (Data.Length > 2)
            //        return new SoapHexBinary((byte[])Data.Skip(Data.Length - 1).Take(1).ToArray()).ToString();
            //    return "ACK REPLY";
            //}
            //set;
            get;
            set;
        }

        //public bool SecondCrypto { get; set; }
        //public bool NeedAck { get; set; }
        //public bool FragmentTail { get; set; }

        public byte[] Seed
        {
            //get
            //{
            //    if (SecondCrypto)
            //        return new SoapHexBinary((byte[])Data.Skip(Data.Length - 4).Take(4).ToArray()).ToString();
            //    return "NO SEED";
            //}
            //set;
            get;
            set;
        }

        public PacketType Type { get; set; }

        public byte[] Data { get; set; }
        public byte[] DataPak { get; set; }

        public T4CBasePak()
        {

        }

        public T4CBasePak(byte[] data)
        {

            Data = data;
            string datafull = new SoapHexBinary(data).ToString();
            ResolveHeader();

            if (SecondCrypto)
            {
                DataPak = Data.Skip(2).Take(Data.Length - 2 - 5).ToArray();
                Seed = Data.Skip(Data.Length - 4).Take(4).ToArray();
                string decodedstring = new SoapHexBinary(DataPak).ToString();
                //DataPak = DecryptionRoutine.Xor(DataPak);
                //DataPak = DecryptionRoutine.Pak_SwitchEncryptionOff_150(DataPak, Seed);
                ActionID = new SoapHexBinary(DataPak.Skip(4).Take(2).ToArray()).ToString();
                Signature = new SoapHexBinary(DataPak.Take(4).ToArray()).ToString();
                DataPak = DataPak.Skip(4).Take(DataPak.Length - 4).ToArray();
            }
            else
            {
                Signature = new SoapHexBinary(Data.Skip(2).Take(4).ToArray()).ToString();
                DataPak = Data.Skip(6).Take(Data.Length - 7).ToArray();
                if (Signature == "99999999")
                {
                    DataPak = DecryptionRoutine.Xor(DataPak);
                }

                //  DataPak = DecryptionRoutine.Xor(DataPak);
                ActionID = new SoapHexBinary(DataPak.Take(2).ToArray()).ToString();

            }
            ResolveData();
            //Signature = GetSignature();
            //ActionID = GetActionID();

        }

        private void ResolveHeader()
        {
            byte[] header = Data.Take(2).Reverse().ToArray();
            byte[] signature = Data.Skip(2).Take(4).ToArray();
            //byte[] decodedheader = DecryptionRoutine.Xor(header);
            //decodedheader = decodedheader.Reverse().ToArray();
            //string decodedstring = new SoapHexBinary(decodedheader).ToString();
            //string t = new SoapHexBinary(Data.Take(2).ToArray().Reverse().ToArray()).ToString();

            ushort headerShort = ushort.Parse(new SoapHexBinary(header).ToString(), System.Globalization.NumberStyles.HexNumber);
            string binaryString = Convert.ToString(headerShort, 2).PadLeft(16, '0');
            string sigHexa = new SoapHexBinary(signature).ToString();

            SecondCrypto = Convert.ToBoolean(Convert.ToInt32(binaryString[13].ToString())) && !sigHexa.Equals("00000000");
            FragmentTail = Convert.ToBoolean(Convert.ToInt32(binaryString[14].ToString()));
            NeedAck = Convert.ToBoolean(Convert.ToInt32(binaryString[15].ToString()));
            Id = (Data.Length == 1024 || FragmentTail) ? Convert.ToInt32(binaryString.Substring(0, 8), 2) : Convert.ToInt32(binaryString.Substring(0, 13), 2);
        }
        /// <summary>
        /// Computes bytes to properties
        /// </summary>
        public virtual void ResolveData()
        {

        }


        private string GetSignature()
        {
            return new SoapHexBinary((byte[])Data.Skip(2).Take(4).ToArray()).ToString();
        }

        private string GetActionID()
        {
            return new SoapHexBinary((byte[])Data.Skip(6).Take(2).ToArray()).ToString();
        }

        public virtual string Display()
        {
            return string.Format("PakID : {0} ", Id);
        }

        public int Id
        {
            get;
            set;
        }


        public bool SecondCrypto
        {
            get;
            set;
        }

        public bool NeedAck
        {
            get;
            set;
        }

        public bool FragmentTail
        {
            get;
            set;
        }

        //public abstract string DisplayData();
    }

    public enum PacketType
    {
        Server,
        Client
    }
}
